let Octokit;
const { Document } = require('@langchain/core/documents');
const BaseRagService = require('./baseRag');
const VectorStoreService = require('../vectorStore');
const { GITHUB_TOKEN, GITHUB_REPOS } = require('./data/githubConfig');

class GithubRagService extends BaseRagService {
  static COLLECTION_NAME = 'githubRag';
  static octokit = null;

  // 初始化数据
  static async initializeData() {
    try {
      // 检查必要的配置
      if (!GITHUB_TOKEN) {
        throw new Error('缺少GITHUB_TOKEN配置');
      }

      // 动态导入@octokit/rest
      const { Octokit: OctokitModule } = await import('@octokit/rest');
      Octokit = OctokitModule;

      // 初始化GitHub客户端
      this.octokit = new Octokit({
        auth: GITHUB_TOKEN
      });

      // 判断向量存储的数据是否存在
      if (!VectorStoreService.vectorStoreCollectionExists(this.COLLECTION_NAME)) {
        // 初始化向量存储
        await VectorStoreService.initCollection(this.COLLECTION_NAME);
        
        // 处理配置的GitHub仓库
        const repos = GITHUB_REPOS;
        for (const repo of repos) {
          try {
            const [owner, repoName] = repo.split('/');
            await this.processRepository(owner, repoName);
            console.log(`成功处理GitHub仓库: ${repo}`);
          } catch (error) {
            console.error(`处理GitHub仓库失败 ${repo}:`, error.message);
          }
        }
      } else {
        // 初始化向量存储
        await VectorStoreService.initCollection(this.COLLECTION_NAME);
        console.log('GitHub RAG集合数据已存在,将会使用原有的集合！');
      }
    } catch (error) {
      console.error('初始化GitHub RAG数据失败:', error.message);
      throw error;
    }
  }

  // 处理GitHub仓库
  static async processRepository(owner, repo) {
    try {
      // 获取仓库信息
      const { data: repoInfo } = await this.octokit.repos.get({
        owner,
        repo
      });

      // 获取仓库的文件树
      const { data: tree } = await this.octokit.git.getTree({
        owner,
        repo,
        tree_sha: repoInfo.default_branch,
        recursive: '1'
      });

      // 处理仓库中的文件
      for (const item of tree.tree) {
        if (item.type === 'blob' && this.isProcessableFile(item.path)) {
          await this.processFile(owner, repo, item.path);
        }
      }
    } catch (error) {
      console.error(`处理仓库失败 ${owner}/${repo}:`, error.message);
      throw error;
    }
  }

  // 处理单个文件
  static async processFile(owner, repo, path) {
    try {
      // 获取文件内容
      const { data } = await this.octokit.repos.getContent({
        owner,
        repo,
        path
      });

      // 解码文件内容
      const content = Buffer.from(data.content, 'base64').toString('utf8');

      const doc = new Document({
        pageContent: content,
        metadata: {
          owner,
          repo,
          path,
          sha: data.sha,
          size: data.size,
          content_type: this.getFileType(path),
          url: data.html_url,
          created_at: new Date().toISOString()
        }
      });

      await this.processContent([doc], this.COLLECTION_NAME);
      console.log(`文件处理完成: ${owner}/${repo}/${path}`);
    } catch (error) {
      console.error(`处理文件失败 ${owner}/${repo}/${path}:`, error.message);
    }
  }

  // 判断文件是否可处理
  static isProcessableFile(path) {
    const processableExtensions = [
      '.md', '.txt', '.js', '.py', '.java', '.cpp', '.c',
      '.h', '.cs', '.php', '.rb', '.swift', '.go', '.rs',
      '.ts', '.jsx', '.tsx', '.vue', '.html', '.css', '.scss',
      '.less', '.json', '.yml', '.yaml', '.xml', '.sh', '.bash'
    ];
    const ext = path.toLowerCase().split('.').pop();
    return processableExtensions.includes(`.${ext}`);
  }

  // 获取文件类型
  static getFileType(path) {
    return path.toLowerCase().split('.').pop();
  }
}

module.exports = GithubRagService;